package thesis.filesharing.dao.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;

import org.springframework.stereotype.Repository;

import thesis.filesharing.common.exception.system.AppSystemException;
import thesis.filesharing.dao.ExerciseFileDAO;
import thesis.filesharing.dao.util.EMF;
import thesis.filesharing.model.Exercise;
import thesis.filesharing.model.ExerciseFile;
import thesis.filesharing.model.Group;
import thesis.filesharing.model.Student;

import com.google.appengine.api.datastore.Key;

@Repository
public class ExerciseFileDAOImpl implements ExerciseFileDAO {
	
	@Override
	public List<ExerciseFile> saveExerciseFileCollection(List<ExerciseFile> exerciseFiles, Key studentKey, Key classKey, Key exerciseKey) {
		EntityManager em = null;
		EntityTransaction transaction = null;
		try {
			em = EMF.get().createEntityManager();
			transaction = em.getTransaction();
			transaction.begin();
			
			Exercise exercise = em.find(Exercise.class, exerciseKey);
			if (exercise != null) {
				exercise.getExerciseFiles().addAll(exerciseFiles);
				if (exercise.getGroupExercise()) {
					// If exercise used for group
					Group g = null;
					Student s = em.find(Student.class, studentKey);
					if (s != null) {
						Set<Key> groupKeys = s.getGroupKeys();
						if (groupKeys != null && !groupKeys.isEmpty()) {
							Group gr = null;
							for (Key groupKey : groupKeys) {
								gr = em.find(Group.class, groupKey);
								if (gr != null && gr.getClazz() != null && gr.getClazz().getClassKey().equals(classKey)) {
									g = gr;
									break;
								}
							}
						}
					}
					if (g != null) {
						for (ExerciseFile f : exerciseFiles) {
							f.setGroup(g);
						}
						g.getExerciseFiles().addAll(exerciseFiles);
					}
				} else {
					// If exercise used for individual
					Student student = em.find(Student.class, studentKey);
					if (student != null) {
						student.getExerciseFiles().addAll(exerciseFiles);
						for (ExerciseFile f : exerciseFiles) {
							f.setStudent(student);
						}
					}
				}
				
				em.merge(exercise);
				em.flush();
			}
			
			transaction.commit();
			return exerciseFiles;
		} catch (Exception ex) {
			if (transaction != null && transaction.isActive()) {
				transaction.rollback();
			}
			ex.printStackTrace();
			throw new AppSystemException(ex);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<ExerciseFile> listExerciseFilesStudentOrGroupUploadedPerExercise(Key exerciseKey, Key studentKey, Key classKey) {
		EntityManager em = null;
		try {
			em = EMF.get().createEntityManager();
			Exercise exercise = em.find(Exercise.class, exerciseKey);
			String jpaql = null;
			if (exercise != null) {
				Query query = null;
				if (exercise.getGroupExercise()) {
					Group g = null;
					Student s = em.find(Student.class, studentKey);
					if (s != null) {
						Set<Key> groupKeys = s.getGroupKeys();
						if (groupKeys != null && !groupKeys.isEmpty()) {
							Group gr = null;
							for (Key groupKey : groupKeys) {
								gr = em.find(Group.class, groupKey);
								if (gr != null && gr.getClazz() != null && gr.getClazz().getClassKey().equals(classKey)) {
									g = gr;
									break;
								}
							}
						}
					}
					if (g != null) {
						jpaql = "SELECT f FROM ExerciseFile f WHERE f.exercise = :exercise AND f.group = :group";
						query = em.createQuery(jpaql);
						query.setParameter("exercise", exercise);
						query.setParameter("group", g);
					}
				} else {
					Student student = em.find(Student.class, studentKey);
					if (student != null) {
						jpaql = "SELECT f FROM ExerciseFile f WHERE f.exercise = :exercise AND f.student = :student";
						query = em.createQuery(jpaql);
						query.setParameter("exercise", exercise);
						query.setParameter("student", student);
					}
				}
				
				if (query != null) {
					return (List<ExerciseFile>) query.getResultList();
				}
			}
			
			return null;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new AppSystemException(ex);
		}
	}

	@Override
	public void deleteExerciseFiles(List<Key> exerciseFileKeys, Key exerciseKey) {
		EntityManager em = null;
		try {
			em = EMF.get().createEntityManager();
			Exercise exercise = em.find(Exercise.class, exerciseKey);
			if (exercise != null) {
				if (exerciseFileKeys != null && !exerciseFileKeys.isEmpty()) {
					List<ExerciseFile> exerciseFiles = new ArrayList<ExerciseFile>();
					for (Key k : exerciseFileKeys) {
						exerciseFiles.add(em.find(ExerciseFile.class, k));
					}
					if (exercise.getGroupExercise()) {
						Group group = exerciseFiles.get(0).getGroup();
						Set<ExerciseFile> files = group.getExerciseFiles();
						List<ExerciseFile> tempList = new ArrayList<ExerciseFile>(files);
						tempList.removeAll(exerciseFiles);
						files.clear();
						files.addAll(tempList);
					} else {
						Student student = exerciseFiles.get(0).getStudent();
						Set<ExerciseFile> files = student.getExerciseFiles();
						List<ExerciseFile> tempList = new ArrayList<ExerciseFile>(files);
						tempList.removeAll(exerciseFiles);
						files.clear();
						files.addAll(tempList);
					}
					exercise.getExerciseFiles().removeAll(exerciseFiles);
					em.merge(exercise);
				}
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new AppSystemException(ex);
		}
	}
}
